#include "ohos_peer_connection.h"
#include <functional>
#include <utility>
#include <vector>
#include "api/rtc_error.h"
#include "api/data_channel_interface.h"
#include "pc/media_session.h"
#include "api/make_ref_counted.h"
#include "ohos_media_stream.h"
#include "ohos_data_channel.h"


namespace ohoswebrtc {

OHOSPeerConnectionDelegateAdapter::~OHOSPeerConnectionDelegateAdapter() {
  
}

void OHOSPeerConnectionDelegateAdapter::RegisterPeerConnectionObserver(OHOSPeerConnectionObserver* observer, rtc::scoped_refptr<OHOSPeerConnectionFactoryInterface> peer_connection_factory) {
  peer_connection_observer_ = observer;
  peer_connection_factory_ = peer_connection_factory;
}

void OHOSPeerConnectionDelegateAdapter::UnRegisterPeerConnectionObserver() {

}

void OHOSPeerConnectionDelegateAdapter::OnSignalingChange(
    webrtc::PeerConnectionInterface::SignalingState new_state) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnSignalingChange(new_state);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnAddStream(
    rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  RTC_LOG(LS_INFO) << __FUNCTION__;
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSMediaStreamInterface> ohos_stream = 
      rtc::scoped_refptr<OHOSMediaStream>(
        new rtc::RefCountedObject<OHOSMediaStream>(
            stream, peer_connection_factory_));
    peer_connection_observer_->OnAddStream(ohos_stream);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnRemoveStream(
    rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSMediaStreamInterface> ohos_stream = 
      rtc::scoped_refptr<OHOSMediaStream>(
        new rtc::RefCountedObject<OHOSMediaStream>(
            stream, peer_connection_factory_));
    peer_connection_observer_->OnRemoveStream(ohos_stream);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnTrack(
    rtc::scoped_refptr<webrtc::RtpTransceiverInterface> nativeTransceiver) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_transceiver = 
      rtc::scoped_refptr<OHOSRtpTransceiver>(
        new rtc::RefCountedObject<OHOSRtpTransceiver>(
            nativeTransceiver, peer_connection_factory_));
    peer_connection_observer_->OnTrack(ohos_transceiver);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnDataChannel(
    rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSDataChannelInterface> ohos_data_channel = 
      rtc::scoped_refptr<OHOSDataChannel>(
        new rtc::RefCountedObject<OHOSDataChannel>(data_channel));
    peer_connection_observer_->OnDataChannel(ohos_data_channel);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnRenegotiationNeeded() {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnRenegotiationNeeded();
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceConnectionChange(
    webrtc::PeerConnectionInterface::IceConnectionState new_state) {
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceConnectionChange(new_state);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnStandardizedIceConnectionChange(
    webrtc::PeerConnectionInterface::IceConnectionState new_state) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnStandardizedIceConnectionChange(new_state);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnConnectionChange(
    webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnConnectionChange(new_state);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceGatheringChange(
    webrtc::PeerConnectionInterface::IceGatheringState new_state) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceGatheringChange(new_state);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceCandidate(
    const webrtc::IceCandidateInterface *candidate) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceCandidate(candidate);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceCandidateError(const std::string &address,
                                                        int port,
                                                        const std::string &url,
                                                        int error_code,
                                                        const std::string &error_text) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceCandidateError(address, port, url, error_code, error_text);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
    const std::vector<cricket::Candidate>& candidates) {
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceCandidatesRemoved(candidates);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnIceSelectedCandidatePairChanged(
    const cricket::CandidatePairChangeEvent &event) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    peer_connection_observer_->OnIceSelectedCandidatePairChanged(event);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnAddTrack(
    rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
    const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSRtpReceiverInterface> ohos_rtp_receiver = 
      rtc::scoped_refptr<OHOSRtpReceiver>(
        new rtc::RefCountedObject<OHOSRtpReceiver>(
            receiver, peer_connection_factory_));
    std::vector<rtc::scoped_refptr<OHOSMediaStreamInterface>> vec;
    for (auto item : streams) {
      rtc::scoped_refptr<OHOSMediaStreamInterface> ohos_stream = rtc::scoped_refptr<OHOSMediaStream>(new rtc::RefCountedObject<OHOSMediaStream>(item, peer_connection_factory_));
      vec.push_back(ohos_stream);
    }
    peer_connection_observer_->OnAddTrack(ohos_rtp_receiver, vec);
  }
}

void OHOSPeerConnectionDelegateAdapter::OnRemoveTrack(
    rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
  RTC_LOG(LS_INFO) << __FUNCTION__;
  RTC_DCHECK(peer_connection_observer_ != nullptr);
  if (peer_connection_observer_ != nullptr) {
    rtc::scoped_refptr<OHOSRtpReceiverInterface> ohos_rtp_receiver = 
      rtc::scoped_refptr<OHOSRtpReceiver>(
        new rtc::RefCountedObject<OHOSRtpReceiver>(
            receiver, peer_connection_factory_));
    peer_connection_observer_->OnRemoveTrack(ohos_rtp_receiver);
  }
}

class OHOSStatsCollectorCallbackAdapter : public webrtc::RTCStatsCollectorCallback {
  public:
    static rtc::scoped_refptr<OHOSStatsCollectorCallbackAdapter> Create(
        OnStatsCollectorCompletion completion) {
      return rtc::scoped_refptr<OHOSStatsCollectorCallbackAdapter>(
        new rtc::RefCountedObject<OHOSStatsCollectorCallbackAdapter>(std::move(completion)));
    }

    explicit OHOSStatsCollectorCallbackAdapter(OnStatsCollectorCompletion completion)
        : completion_(std::move(completion)) {}
    ~OHOSStatsCollectorCallbackAdapter() override = default;

    void OnStatsDelivered(const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override {
      RTC_LOG(LS_INFO) << __FUNCTION__;
      completion_(report);
    }

  private:
    OnStatsCollectorCompletion completion_;
};


class SetLocalDescriptionObserverAdapter
    : public webrtc::SetLocalDescriptionObserverInterface {
  public:
    static rtc::scoped_refptr<SetLocalDescriptionObserverAdapter> Create(OnSdpDescriptionCallback callback) {
      return rtc::scoped_refptr<SetLocalDescriptionObserverAdapter>(
        new rtc::RefCountedObject<SetLocalDescriptionObserverAdapter>(std::move(callback)));
    }

    explicit SetLocalDescriptionObserverAdapter(OnSdpDescriptionCallback callback) : callback_(std::move(callback)) {}
    ~SetLocalDescriptionObserverAdapter() override = default;

  private:
    void OnSetLocalDescriptionComplete(webrtc::RTCError error) override {
      RTC_LOG(LS_INFO) << __FUNCTION__;
      callback_(std::move(error));
    }

  private:
    OnSdpDescriptionCallback callback_;
};

class SetRemoteDescriptionObserverAdapter
    : public webrtc::SetRemoteDescriptionObserverInterface {
  public:
    static rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter> Create(
        OnSdpDescriptionCallback callback) {
      return rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter>(
        new rtc::RefCountedObject<SetRemoteDescriptionObserverAdapter>(std::move(callback)));
    }

    explicit SetRemoteDescriptionObserverAdapter(OnSdpDescriptionCallback callback)
        : callback_(std::move(callback)) {}
    ~SetRemoteDescriptionObserverAdapter() override = default;

  private:
    void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
      RTC_LOG(LS_INFO) << __FUNCTION__;
      callback_(std::move(error));
    }

  private:
    OnSdpDescriptionCallback callback_;
};

class CreateSessionDescriptionObserverAdapter
    : public webrtc::CreateSessionDescriptionObserver {
 
 public: 
  static CreateSessionDescriptionObserverAdapter *Create(CreateSessionDescriptionSuccess success, CreateSessionDescriptionFailure failure) {
    return new rtc::RefCountedObject<CreateSessionDescriptionObserverAdapter>(std::move(success), std::move(failure));
  }

  CreateSessionDescriptionObserverAdapter(CreateSessionDescriptionSuccess success, CreateSessionDescriptionFailure failure)
      : success_(std::move(success)),
        failure_(std::move(failure)) {
    RTC_LOG(LS_INFO) << __FUNCTION__;
  }

  ~CreateSessionDescriptionObserverAdapter() override = default;

 private:
  void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
    success_(desc);
  }

  void OnFailure(webrtc::RTCError error) override {
    failure_(std::move(error));
  }

 private:
  CreateSessionDescriptionSuccess success_;
  CreateSessionDescriptionFailure failure_;
};

OHOSPeerConnection::OHOSPeerConnection(webrtc::PeerConnectionInterface::RTCConfiguration &configuration,
                                      rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints,
                                      OHOSPeerConnectionObserver *observer,
                                      rtc::scoped_refptr<OHOSPeerConnectionFactoryInterface> peer_connection_factory) 
    : peer_connection_factory_(peer_connection_factory),
      constraints_(constraints) {
  RTC_LOG(LS_INFO) << __FUNCTION__ << ": Ctor";
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK_RUN_ON(peer_connection_factory->signaling_thread());
  adapter_observer_.reset(new OHOSPeerConnectionDelegateAdapter());
  webrtc::PeerConnectionDependencies dependencies(adapter_observer_.get());
  webrtc::MediaConstraints rtc_constraints(constraints->GetMandatory(),
                                           constraints->GetOptional());

  auto config = std::make_unique<webrtc::PeerConnectionInterface::RTCConfiguration>(configuration);

  webrtc::CopyConstraintsIntoRtcConfiguration(&rtc_constraints, config.get());
  webrtc::PeerConnectionFactoryInterface::Options options;
  peer_connection_factory_->peer_connection_factory()->SetOptions(options);

  auto result = peer_connection_factory_->peer_connection_factory()->CreatePeerConnectionOrError(*config, std::move(dependencies));
  if (!result.ok()) {
    return;
  }
  peer_connection_ = result.MoveValue();
  if (observer) {
    webrtc::MutexLock lock(&pc_mutex_);
    adapter_observer_->RegisterPeerConnectionObserver(observer, peer_connection_factory_);
  }
}

OHOSPeerConnection::~OHOSPeerConnection() {
  // Close();
  RTC_LOG(LS_INFO) << __FUNCTION__ << ": dtor";
}

void OHOSPeerConnection::RegisterPeerConnectionObserver(
      OHOSPeerConnectionObserver* observer) {
  RTC_DCHECK(peer_connection_factory_);
  if (adapter_observer_.get() == nullptr) {
    return;
  }
  webrtc::MutexLock lock(&pc_mutex_);
  adapter_observer_->RegisterPeerConnectionObserver(observer, peer_connection_factory_);
}

void OHOSPeerConnection::UnRegisterPeerConnectionObserver() {
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  webrtc::MutexLock lock(&pc_mutex_);
  adapter_observer_->UnRegisterPeerConnectionObserver();
}

void OHOSPeerConnection::AddIceCandidate(const webrtc::IceCandidateInterface* candidate) {
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK(peer_connection_ != nullptr);
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      AddIceCandidate(candidate);
    });
  }
  if (peer_connection_ != nullptr) {
    peer_connection_->AddIceCandidate(candidate);
  }
}

void OHOSPeerConnection::AddIceCandidate(const std::string sdp, int sdp_mline_index, const std::string sdp_mid) {
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK(peer_connection_ != nullptr);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      AddIceCandidate(sdp, sdp_mline_index, sdp_mid);
    });
  }
  
  webrtc::SdpParseError error;
  std::unique_ptr<webrtc::IceCandidateInterface> owned_candidate(
      webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp, &error));
  if (owned_candidate) {
    peer_connection_->AddIceCandidate(owned_candidate.get());
  }
}

void OHOSPeerConnection::RemoveIceCandidate(const webrtc::IceCandidateInterface* candidate) {
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK(peer_connection_ != nullptr);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      RemoveIceCandidate(candidate);
    });
  }
  
  std::vector<cricket::Candidate> candidates;
  if (candidate) {
    candidates.push_back(candidate->candidate());
      // Need to fill the transport name from the sdp_mid.
    candidates.back().set_transport_name(candidate->sdp_mid());
  }
  if (!candidates.empty()) {
    peer_connection_->RemoveIceCandidates(candidates);
  }
}

void OHOSPeerConnection::SetConfiguration(const webrtc::PeerConnectionInterface::RTCConfiguration& configuration) {
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK(peer_connection_ != nullptr);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetConfiguration(configuration);
    });
  }
  
  auto config = std::make_unique<webrtc::PeerConnectionInterface::RTCConfiguration>(configuration);
  if (!config) {
    return;
  }
  webrtc::MediaConstraints constraints(constraints_->GetMandatory(),constraints_->GetOptional());
  webrtc::CopyConstraintsIntoRtcConfiguration(&constraints,
                                      config.get());
  peer_connection_->SetConfiguration(*config).ok();
}

void OHOSPeerConnection::Close() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  
  RTC_LOG(LS_INFO) << __FUNCTION__<< "";
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      Close();
    });
  }
  if (peer_connection_) {
    peer_connection_->Close();
    peer_connection_ = nullptr;
    local_streams_.clear();
  }
}

bool OHOSPeerConnection::AddStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return false;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddStream(stream);
    });
  }
  
  OHOSMediaStream* send_stream = static_cast<OHOSMediaStream*>(stream.get());
  rtc::scoped_refptr<webrtc::MediaStreamInterface> media_stream =
      send_stream->media_stream();

  auto it = std::find(local_streams_.begin(), local_streams_.end(), stream);
  if (it != local_streams_.end()) {
    // 找到了 stream
    RTC_LOG(LS_ERROR) << "Stream found in local_streams_!";
    return false;
  }

  if (!peer_connection_->AddStream(media_stream.get())) {
    RTC_LOG(LS_ERROR) << "Failed to add stream:";
    return false;
  }
  local_streams_.push_back(stream);
  return true;
}

void OHOSPeerConnection::RemoveStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return RemoveStream(stream);
    });
  }
  
  OHOSMediaStream* send_stream = static_cast<OHOSMediaStream*>(stream.get());
  rtc::scoped_refptr<webrtc::MediaStreamInterface> media_stream =
      send_stream->media_stream();
  auto it = std::find(local_streams_.begin(), local_streams_.end(), stream);
  if (it != local_streams_.end()) {
    peer_connection_->RemoveStream(media_stream.get());
    local_streams_.erase(std::find(local_streams_.begin(), local_streams_.end(), stream));
  } else {
    RTC_LOG(LS_ERROR) << "no remove stream:";
  }
}

rtc::scoped_refptr<OHOSRtpSenderInterface> OHOSPeerConnection::AddTrack(
  rtc::scoped_refptr<OHOSMediaTrackInterface> track, const std::vector<std::string> streamIds) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return rtc::scoped_refptr<OHOSRtpSenderInterface>();
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddTrack(track, streamIds);
    });
  }
  
  OHOSMediaTrackInterface* media_track = static_cast<OHOSMediaTrackInterface*>(track.get());
  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> native_sender_or_error =
      peer_connection_->AddTrack(media_track->track(), streamIds);
  if (!native_sender_or_error.ok()) {
    RTC_LOG(LS_ERROR) << "Failed to add track " <<  native_sender_or_error.error().message();
    return rtc::scoped_refptr<OHOSRtpSenderInterface>();
  }
  return rtc::scoped_refptr<OHOSRtpSenderInterface>(new rtc::RefCountedObject<OHOSRtpSender>(
              native_sender_or_error.MoveValue(), peer_connection_factory_));
}

bool OHOSPeerConnection::RemoveTrack(rtc::scoped_refptr<OHOSRtpSenderInterface> sender) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return false;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return RemoveTrack(sender);
    });
  }
  
  OHOSRtpSender* rtp_sender = static_cast<OHOSRtpSender*>(sender.get());
  if (rtp_sender->rtp_sender().get() != nullptr) {
    webrtc::RTCError result = peer_connection_->RemoveTrackOrError(rtp_sender->rtp_sender());
    if (result.ok()) {
      RTC_LOG(LS_ERROR) << "removeTrack success ";
      return true;
    };
  }
  return false;
}

rtc::scoped_refptr<OHOSRtpTransceiverInterface> OHOSPeerConnection::AddTransceiver(
      rtc::scoped_refptr<OHOSMediaTrackInterface> track) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddTransceiver(track);
    });
  }
  
  OHOSMediaTrackInterface* media_track = static_cast<OHOSMediaTrackInterface*>(track.get());
  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> errorOr = peer_connection_->AddTransceiver(media_track->track());
  if (errorOr.ok()) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_transceiver = 
      rtc::scoped_refptr<OHOSRtpTransceiver>(
        new rtc::RefCountedObject<OHOSRtpTransceiver>(
            errorOr.value(), peer_connection_factory_));
    return ohos_transceiver;
  }

  return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
}

rtc::scoped_refptr<OHOSRtpTransceiverInterface> OHOSPeerConnection::AddTransceiver(
      rtc::scoped_refptr<OHOSMediaTrackInterface> track,
      const webrtc::RtpTransceiverInit &init) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddTransceiver(track, init);
    });
  }
  
  OHOSMediaTrackInterface* media_track = static_cast<OHOSMediaTrackInterface*>(track.get());
  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
      errorOr = peer_connection_->AddTransceiver(media_track->track(), init);
  if (errorOr.ok()) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_transceiver = 
      rtc::scoped_refptr<OHOSRtpTransceiver>(
        new rtc::RefCountedObject<OHOSRtpTransceiver>(
            errorOr.value(), peer_connection_factory_));
    return ohos_transceiver;
  }
  return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
}

rtc::scoped_refptr<OHOSRtpTransceiverInterface> OHOSPeerConnection::AddTransceiver(
  cricket::MediaType media_type) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddTransceiver(media_type);
    });
  }
  
  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
      errorOr = peer_connection_->AddTransceiver(media_type);
  if (errorOr.ok()) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_transceiver = 
      rtc::scoped_refptr<OHOSRtpTransceiver>(
        new rtc::RefCountedObject<OHOSRtpTransceiver>(
            errorOr.value(), peer_connection_factory_));
    return ohos_transceiver;
  }
  return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
}

rtc::scoped_refptr<OHOSRtpTransceiverInterface> OHOSPeerConnection::AddTransceiver(
  cricket::MediaType media_type, const webrtc::RtpTransceiverInit &init) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
  }

  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return AddTransceiver(media_type, init);
    });
  }
  
  webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
      errorOr = peer_connection_->AddTransceiver(media_type, init);
  if (errorOr.ok()) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_transceiver = 
      rtc::scoped_refptr<OHOSRtpTransceiver>(
        new rtc::RefCountedObject<OHOSRtpTransceiver>(
            errorOr.value(), peer_connection_factory_));
    return ohos_transceiver;
  }
  return rtc::scoped_refptr<OHOSRtpTransceiverInterface>();
}

void OHOSPeerConnection::CreateOffer(rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints,
                                     CreateSessionDescriptionSuccess success,
                                     CreateSessionDescriptionFailure failure) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    failure(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      CreateOffer(constraints, success, failure);
    });
  }

  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
  webrtc::MediaConstraints webrtc_media_constraints(constraints->GetMandatory(),
                                           constraints->GetOptional());
  webrtc::CopyConstraintsIntoOfferAnswerOptions(&webrtc_media_constraints,
                                            &offer_answer_options);
  peer_connection_->CreateOffer(
      CreateSessionDescriptionObserverAdapter::Create(success, failure),
      offer_answer_options);
}

void OHOSPeerConnection::CreateOffer(webrtc::CreateSessionDescriptionObserver* observer,
                                     rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      CreateOffer(observer, constraints);
    });
  }
  
  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
  webrtc::MediaConstraints webrtc_media_constraints(constraints->GetMandatory(),
                                           constraints->GetOptional());
  webrtc::CopyConstraintsIntoOfferAnswerOptions(&webrtc_media_constraints,
                                            &offer_answer_options);
  peer_connection_->CreateOffer(observer,offer_answer_options);                                    
}

void OHOSPeerConnection::CreateAnswer(rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints,
                                      CreateSessionDescriptionSuccess success,
                                      CreateSessionDescriptionFailure failure) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    failure(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    return;
  }

  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      CreateAnswer(constraints, success, failure);
    });
  }
  
  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
  webrtc::MediaConstraints webrtc_media_constraints(constraints->GetMandatory(),
                                           constraints->GetOptional());
  webrtc::CopyConstraintsIntoOfferAnswerOptions(&webrtc_media_constraints,
                                            &offer_answer_options);
  peer_connection_->CreateAnswer(
      CreateSessionDescriptionObserverAdapter::Create(success, failure),
      offer_answer_options);
}

void OHOSPeerConnection::CreateAnswer(webrtc::CreateSessionDescriptionObserver* observer,
                                      rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }

  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      CreateAnswer(observer, constraints);
    });
  }
  
  webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
  webrtc::MediaConstraints webrtc_media_constraints(constraints->GetMandatory(),
                                           constraints->GetOptional());
  webrtc::CopyConstraintsIntoOfferAnswerOptions(&webrtc_media_constraints,
                                            &offer_answer_options);
  peer_connection_->CreateAnswer(observer,offer_answer_options);
}

void OHOSPeerConnection::SetLocalDescription(OnSdpDescriptionCallback callback) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetLocalDescription(callback);
    });
  }
  
  peer_connection_->SetLocalDescription(SetLocalDescriptionObserverAdapter::Create(callback)); 
}

void OHOSPeerConnection::SetLocalDescription(rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetLocalDescription(observer);
    });
  }
  peer_connection_->SetLocalDescription(observer); 
}

void OHOSPeerConnection::SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                             OnSdpDescriptionCallback callback) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    if (callback) {
      callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    }
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      peer_connection_->SetLocalDescription(std::move(sdp_desc), SetLocalDescriptionObserverAdapter::Create(callback)); 
    });
  }
  
  RTC_LOG(LS_INFO) << "peer connection SetLocalDescription";
  peer_connection_->SetLocalDescription(std::move(sdp_desc), SetLocalDescriptionObserverAdapter::Create(callback)); 
}

void OHOSPeerConnection::SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                             rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      peer_connection_->SetLocalDescription(std::move(sdp_desc), observer); 
    });
  }
  RTC_LOG(LS_INFO) << "peer connection SetLocalDescription";
  peer_connection_->SetLocalDescription(std::move(sdp_desc), observer); 
}

void OHOSPeerConnection::SetLocalDescription(const std::string sdp_desc,
                                              webrtc::SdpType sdp_type,
                                              OnSdpDescriptionCallback callback) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    if (callback) {
      callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    }
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetLocalDescription(sdp_desc, sdp_type, callback);
    });
  }
  
  webrtc::SdpParseError error;
  std::unique_ptr<webrtc::SessionDescriptionInterface> session_description = webrtc::CreateSessionDescription(sdp_type, sdp_desc, &error);
  if (!session_description) {
    RTC_LOG(LS_WARNING) << "session_description create error";
    if (callback) {
      callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "session_description create error"));
    }
    return;
  };
  RTC_LOG(LS_INFO) << "peer connection SetLocalDescription";
  peer_connection_->SetLocalDescription(std::move(session_description), SetLocalDescriptionObserverAdapter::Create(callback));                            
}
    
void OHOSPeerConnection::SetLocalDescription(const std::string sdp_desc,
                                              webrtc::SdpType sdp_type,
                                              rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetLocalDescription(sdp_desc, sdp_type, observer);
    });
  }
  webrtc::SdpParseError error;
  std::unique_ptr<webrtc::SessionDescriptionInterface> session_description = webrtc::CreateSessionDescription(sdp_type, sdp_desc, &error);
  if (!session_description) {
    RTC_LOG(LS_WARNING) << "session_description create error";
    return;
  };
  RTC_LOG(LS_INFO) << "peer connection SetLocalDescription";
  peer_connection_->SetLocalDescription(std::move(session_description), observer);                            
}

void OHOSPeerConnection::SetRemoteDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                              OnSdpDescriptionCallback callback) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      peer_connection_->SetRemoteDescription(std::move(sdp_desc),
      SetRemoteDescriptionObserverAdapter::Create(callback)); 
    });
  }
  
  peer_connection_->SetRemoteDescription(std::move(sdp_desc),
      SetRemoteDescriptionObserverAdapter::Create(callback));                               
}

void OHOSPeerConnection::SetRemoteDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                              rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      peer_connection_->SetRemoteDescription(std::move(sdp_desc), observer);   ;
    });
  }
  peer_connection_->SetRemoteDescription(std::move(sdp_desc), observer);
}

void OHOSPeerConnection::SetRemoteDescription(const std::string sdp_desc,
                                               webrtc::SdpType sdp_type,
                                               OnSdpDescriptionCallback callback) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    if (callback) {
      callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "peer_connection or peer_connection_factory null"));
    }
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetRemoteDescription(sdp_desc, sdp_type, callback);
    });
  }
  
  webrtc::SdpParseError error;
  std::unique_ptr<webrtc::SessionDescriptionInterface> session_description = webrtc::CreateSessionDescription(sdp_type, sdp_desc, &error);
  if (!session_description) {
    RTC_LOG(LS_WARNING) << "session_description create error";
    if (callback) {
      callback(webrtc::RTCError(
          webrtc::RTCErrorType::INVALID_PARAMETER,
          "session_description create error"));
    }
    return;
  };
  peer_connection_->SetRemoteDescription(std::move(session_description),
      SetRemoteDescriptionObserverAdapter::Create(callback));                            
}

void OHOSPeerConnection::SetRemoteDescription(const std::string sdp_desc,
                                               webrtc::SdpType sdp_type,
                                               rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_ERROR) << "peer_connection or peer_connection_factory null";
    return;
  }
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      SetRemoteDescription(sdp_desc, sdp_type, observer);
    });
  }
  webrtc::SdpParseError error;
  std::unique_ptr<webrtc::SessionDescriptionInterface> session_description = webrtc::CreateSessionDescription(sdp_type, sdp_desc, &error);
  if (!session_description) {
    RTC_LOG(LS_ERROR) << "session_description create error";
    return;
  };
  peer_connection_->SetRemoteDescription(std::move(session_description),observer);                            
}

void OHOSPeerConnection::GetStats(OnStatsCollectorCompletion completion) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    if (completion) {

    }
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      GetStats(completion);
    });
  }

  rtc::scoped_refptr<OHOSStatsCollectorCallbackAdapter> stats_callback =
      OHOSStatsCollectorCallbackAdapter::Create(completion);
  peer_connection_->GetStats(stats_callback.get());
}

std::vector<rtc::scoped_refptr<OHOSRtpSenderInterface>> OHOSPeerConnection::senders() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  std::vector<rtc::scoped_refptr<OHOSRtpSenderInterface>> vec;
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    std::vector<rtc::scoped_refptr<OHOSRtpSenderInterface>> vec;
    return vec;
  }

  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return senders();
    });
  }
  
  for (auto item : peer_connection_->GetSenders()) {
    rtc::scoped_refptr<OHOSRtpSenderInterface> ohos_rtp_sender = rtc::scoped_refptr<OHOSRtpSenderInterface>(new rtc::RefCountedObject<OHOSRtpSender>(item, peer_connection_factory_));
    vec.push_back(ohos_rtp_sender);
  }
  return vec;
}

std::vector<rtc::scoped_refptr<OHOSRtpTransceiverInterface>> OHOSPeerConnection::transceivers() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    std::vector<rtc::scoped_refptr<OHOSRtpTransceiverInterface>> vec;
    return vec;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return transceivers();
    });
  }
  
  std::vector<rtc::scoped_refptr<OHOSRtpTransceiverInterface>> vec;
  for (auto item : peer_connection_->GetTransceivers()) {
    rtc::scoped_refptr<OHOSRtpTransceiverInterface> ohos_rtp_transceiver = rtc::scoped_refptr<OHOSRtpTransceiverInterface>(new rtc::RefCountedObject<OHOSRtpTransceiver>(item, peer_connection_factory_));
    vec.push_back(ohos_rtp_transceiver);
  }
  return vec;
}

std::vector<rtc::scoped_refptr<OHOSRtpReceiverInterface>> OHOSPeerConnection::receivers() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    std::vector<rtc::scoped_refptr<OHOSRtpReceiverInterface>> vec;
    return vec;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return receivers();
    });
  }

  std::vector<rtc::scoped_refptr<OHOSRtpReceiverInterface>> vec;
  for (auto item : peer_connection_->GetReceivers()) {
    rtc::scoped_refptr<OHOSRtpReceiverInterface> ohos_rtp_receiver = rtc::scoped_refptr<OHOSRtpReceiverInterface>(new rtc::RefCountedObject<OHOSRtpReceiver>(item, peer_connection_factory_));
    vec.push_back(ohos_rtp_receiver);
  }
  return vec;
}

webrtc::PeerConnectionInterface::SignalingState OHOSPeerConnection::signaling_state() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return webrtc::PeerConnectionInterface::SignalingState::kStable;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return signaling_state();
    });
  }
  
  return peer_connection_->signaling_state();
}

webrtc::PeerConnectionInterface::IceConnectionState OHOSPeerConnection::ice_connection_state() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return webrtc::PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return ice_connection_state();
    });
  }
  
  return peer_connection_->ice_connection_state();
}

webrtc::PeerConnectionInterface::IceConnectionState OHOSPeerConnection::standardized_ice_connection_state() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return webrtc::PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return standardized_ice_connection_state();
    });
  }
  
  return peer_connection_->standardized_ice_connection_state();
}

webrtc::PeerConnectionInterface::PeerConnectionState OHOSPeerConnection::peer_connection_state() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return webrtc::PeerConnectionInterface::PeerConnectionState::kNew;
  }
  return peer_connection_->peer_connection_state();
}

webrtc::PeerConnectionInterface::IceGatheringState OHOSPeerConnection::ice_gathering_state() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return ice_gathering_state();
    });
  }
  
  return peer_connection_->ice_gathering_state();
}

absl::optional<bool> OHOSPeerConnection::can_trickle_ice_candidates() {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    absl::optional<bool> optional_bool(false);
    return optional_bool;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
      return can_trickle_ice_candidates();
    });
  }
  
  return peer_connection_->can_trickle_ice_candidates();
}

void OHOSPeerConnection::AddAdaptationResource(rtc::scoped_refptr<webrtc::Resource> resource) {
  RTC_DCHECK(peer_connection_);
  RTC_DCHECK(peer_connection_factory_);
  if (!peer_connection_ || !peer_connection_factory_) {
    RTC_LOG(LS_WARNING) << "peer_connection or peer_connection_factory null";
    return;
  }
  
  if (rtc::Thread::Current() != peer_connection_factory_->signaling_thread()) {
    return peer_connection_factory_->signaling_thread()->BlockingCall([&] {
       AddAdaptationResource(resource);
    });
  }
  
  peer_connection_->AddAdaptationResource(resource);
}

}  // namespace ohoswebrtc